# ================= 导入基础的组件  ===========
from utils.base_import import *
# ================= 导入组件 ================
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
# ================= 序列化的类 ================
from useweb.serializer import PositionSerializer, StaffSerializer, RolesSerializer, PermissionSerializer, ButtonSerializer, RolesPermissionDetailSerializer
# =========== 导入数据类 ============
from useweb.models import Position, Staff, Roles, Permission, Button, RolesPermission, RolesPermissonDetail
from basicweb.models import AreaPlace, BranchArea, Branch
# ========= 导入分页的类 ================
from utils.paginations import MyPageNumberPagination
# ========== 导入filter的类 =====================
from useweb.filters import StaffFilter
# ================ 导入action =================
from rest_framework.decorators import action
# ================ 导入Response ================
from rest_framework.response import Response
from rest_framework import status
# ============= 导入jwt token获取 ==============
from utils import jwt_token
# ========== 导入验证码的组件 ==================
from utils.imagecode.image_code import check_code
from io import BytesIO


# # 职位
class PositionViews(ModelViewSet):
    queryset = Position.objects.all()
    serializer_class = PositionSerializer


# 按钮
class ButtonViews(ModelViewSet):
    queryset = Button.objects.all()
    serializer_class = ButtonSerializer


# 员工
class StaffViews(ModelViewSet):
    queryset = Staff.objects.all().distinct()
    serializer_class = StaffSerializer

    pagination_class = MyPageNumberPagination

    search_fields = ('id', 'name', 'mobile','email')
    filter_class = StaffFilter

    @action(methods=['get'], detail=False, url_path="select")
    def list_all_select(self,request, *args, **kwarg):
        # 获取所有的员工id和name
        staff_objs = list(Staff.objects.all().values('id','name'))
        # 返回
        return Response({'data': staff_objs}, status=status.HTTP_200_OK)

    @action(methods=['post'], detail=False, url_path="select/branch")
    def list_branch_select(self, request, *args, **kwarg):
        # 获取分部的id
        branch_id = request.data.get('branch_id')
        # 获取相应分部下的的员工id和name
        staff_objs = list(Staff.objects.filter(areaplace__brancharea__branch_id=branch_id).values('id', 'name').distinct())
        # 返回
        return Response({'data': staff_objs}, status=status.HTTP_200_OK)


    def create(self,request, *args, **kwargs):
            # 获取传递的数据
            data = request.data
            try:
                # 第一步:  添加员工信息
                Staff.objects.create(id=data.get('id'), name=data.get('name'), position_id=data.get('position'), pwd=data.get('pwd'),
                status=data.get('status'), create_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"), mobile=data.get('mobile'),
                email=data.get('email'))

                # 获取当前添加的员工
                obj_staff = Staff.objects.get(id=data.get('id'))


                #========= 第二步：添加员工和场地的映射===========
                placecode = data.get('placecode')
                # 遍历
                for item in placecode:
                    # 判断是否是三个元素
                    if len(item) == 3:
                        # 获取当前的场地
                        one_placecode = item[-1]
                        # 实例化场地对象
                        obj_place = AreaPlace.objects.get(code=one_placecode)
                        # 添加映射
                        obj_staff.areaplace.add(obj_place)

                # ========= 第三步：添加员工和角色的映射===========
                # 遍历
                for item in data.get('roles'):
                    # 实例化角色的对象
                    obj_roles = Roles.objects.get(id=item)
                    # 添加映射
                    obj_roles.staff.add(obj_staff)



                return Response({'msg': '返回成功！'},status=status.HTTP_201_CREATED)
            except Exception as e:
                return Response({'error': '添加出现异常！'}, status=status.HTTP_400_BAD_REQUEST)

    def update(self,request, *args, **kwargs):
        # 获取当前的员工的id
        pk = kwargs.get('pk')
        # 获取表单的数据
        rec = request.data

        # ====第一步：修改常规的属性 ====
        Staff.objects.filter(pk=pk).update(name=rec.get('name'), pwd=rec.get('pwd'), position_id=rec.get('position').get('id'), status=rec.get('status'),
                                           mobile=rec.get('mobile'), email=rec.get('email'), edit_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        # === 第二步：修改用户和场地的关联 ====
        # 获取当前用户数据库中存储的场地管理
        db_list = list(AreaPlace.objects.filter(staff__id=pk).values_list('code', flat=True))
        # 获取表单传递过来的场地
        form_list = rec.get('placecode')
        # 定义集合
        rec_list = []

        # 判断子元素是否是list集合
        if len(form_list) != 0 and type(form_list[0]) is list:
            for item in form_list:
                if len(item) == 3:
                    rec_list.append(item[-1])
        else:
            rec_list = form_list

        # 需要添加的场地 ---->  rec_list - db_list
        add_list = list(set(rec_list) - set(db_list))

        # 需要删除的场地 ---->  db_list - rec_list
        remove_list = list(set(db_list) - set(rec_list))

        # == 遍历删除 ====
        obj_Staff = Staff.objects.get(pk=pk)
        # 遍历
        for item in remove_list:
            # 实例化场地对象
            obj_Place = AreaPlace.objects.get(pk=item)
            # 删除
            obj_Staff.areaplace.remove(obj_Place)

        # === 批量添加 ====
        for item in add_list:
            # 实例化场地对象
            obj_Place = AreaPlace.objects.get(pk=item)
            # 删除
            obj_Staff.areaplace.add(obj_Place)

        # === 第三步：修改用户和角色的关联 ====
        # 获取数据库中记录的当前用户的角色
        db_roles_list = list(Roles.objects.filter(staff__id=pk).values_list('id', flat=True))
        # 获取表单传递过来的角色信息
        form_roles_list = rec.get('roles')
        # 需要添加的角色
        add_roles_list = list(set(form_roles_list) - set(db_roles_list))
        # 需要删除的角色
        remove_roles_list = list(set(db_roles_list) -set(form_roles_list))
        # 批量删除
        for item in remove_roles_list:
            # 实例化
            obj_roles = Roles.objects.get(id=item)
            # 删除
            obj_roles.staff.remove(obj_Staff)
        # 批量添加
        for item in add_roles_list:
            # 实例化
            obj_roles = Roles.objects.get(id=item)
            # 删除
            obj_roles.staff.add(obj_Staff)


        return Response(status=status.HTTP_201_CREATED)

    @action(methods=['post'], detail=True, url_path="ch/status")
    def change_status(self, request, *args, **kwargs):
        # 获取当前的id
        pk = kwargs.get('pk')
        # 获取当前员工的状态
        staff_obj = Staff.objects.filter(pk=pk).first()
        # 修改状态
        staff_obj.status = request.data.get('status')
        # 更新修改时间
        staff_obj.edit_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 保存
        staff_obj.save()
        # 返回
        return Response(status=status.HTTP_200_OK)

    @action(methods=['post', 'get'],detail=False, url_path="login")
    def staff_login(self, request, *args, **kwargs):
        # 获取传递的用户名和密码
        rec = request.data
        # 1. 当前用户是否存在
        staff_obj = Staff.objects.filter(Q(id=rec.get("id")) | Q(mobile=rec.get('id')) | Q(email=rec.get('id'))).first()
        # === 判断 ===
        if not staff_obj:
            return Response({'error': "当前用户不存在！"}, status=status.HTTP_401_UNAUTHORIZED)
        # 2. 判断当前是否禁用
        if not staff_obj.status:
            return Response({'error': "当前用户已禁用！"}, status=status.HTTP_401_UNAUTHORIZED)
        # 3. 判断密码是否正确
        if staff_obj.pwd != rec.get('pwd'):
            return Response({'error': "密码错误！"}, status=status.HTTP_401_UNAUTHORIZED)

        # 4. 获取jwt token并返回
        token = jwt_token.create_token({'id': staff_obj.id, 'name': staff_obj.name})

        # 返回
        return Response({'token': token}, status=status.HTTP_200_OK)


# 角色
class RolesViews(ModelViewSet):
    queryset = Roles.objects.all()
    serializer_class = RolesSerializer

    pagination_class = MyPageNumberPagination
    search_fields = ('name', 'desc')

    @action(methods=['post'], detail=True, url_path="list/permissions")
    def list_permission(self, request, *args, **kwargs):
        # 获取当前的id -- roles的id
        pk = kwargs.get('pk')
        # 定义集合存储权限
        permission_list = []
        # 获取所有的Rolespermission
        RolesPermission_objs = RolesPermission.objects.filter(roles__id=pk)
        # 遍历集合
        for item in RolesPermission_objs:
            # 获取所有的按钮权限
            RolesPermissionDetail_objs = RolesPermissonDetail.objects.filter(rolespermission_id = item.id)
            # 遍历
            for value in RolesPermissionDetail_objs:
               permission_list.append(int("%d%02d" %(item.permission_id, value.button_id)))


        # 返回
        return Response({'data': permission_list}, status=status.HTTP_200_OK)


    @action(methods=['post'], detail=True)
    def assign(self, request, *args, **kwargs):
        # 获取当前的id -- roles的id
        pk = kwargs.get('pk')
        # ============== 获取表单提交来的权限 ==================
        # 获取传递的权限
        permissions = request.data.get('permissions')
        # 把传递来的权限组合XXXX [前两位模块，后两位按钮]
        form_permission_list = []
        # 便利
        for item in permissions:
            if len(str(item)) >= 3:
                form_permission_list.append(item)

        # ============== 获取表单提交来的权限 ==================
        db_permissions = RolesPermission.objects.filter(roles__id=pk)
        # 定义集合
        db_permission_list = []
        # 遍历
        for item in db_permissions:
            # 获取具体的权限
            permissiondetail_objs = RolesPermissonDetail.objects.filter(rolespermission_id=item.id)
            # 便利
            for detail in permissiondetail_objs:
                # 附加
                db_permission_list.append("%d%02d" % (item.permission_id, detail.button_id))

        # =========== 获取需要添加的按钮 ===========
        add_permission = list(set(form_permission_list) - set(db_permission_list))
        remove_permission = list(set(db_permission_list) - set(form_permission_list))

        #开始删除权限
        for item in remove_permission:
            # 获取当前的权限
            one_permission = int(item[:-2])
            one_permission_detail = int(item[-2:])
            # 获取权限对象
            obj_rolespermission = RolesPermission.objects.filter(roles_id=pk, permission_id=one_permission).first()
            # 删除
            RolesPermissonDetail.objects.filter(button_id=one_permission_detail, rolespermission_id=obj_rolespermission.id).delete()
            # 判断页面权限下是否有按钮权限
            is_exists = RolesPermissonDetail.objects.filter(rolespermission_id=obj_rolespermission.id).exists()
            # 如果找不到
            if not is_exists:
                RolesPermission.objects.filter(roles_id=pk, permission_id=one_permission).delete()

        # 开始添加
        for item in add_permission:
            # 获取当前的权限
            one_permission = int(item[:-2])
            one_permission_detail = int(item[-2:])
            # 获取权限对象
            obj_rolespermission = RolesPermission.objects.filter(roles_id=pk, permission_id=one_permission).first()
            # 判断是否为空
            if not obj_rolespermission:
                # 添加
                RolesPermission.objects.create(roles_id=pk, permission_id=one_permission)
                # 获取Id
                obj_rolespermission = RolesPermission.objects.filter(roles_id=pk, permission_id=one_permission).first()
            # 写入全新
            RolesPermissonDetail.objects.create(rolespermission_id=obj_rolespermission.id, button_id=one_permission_detail)

        # 返回
        return Response(status=status.HTTP_200_OK)


        """
        # =========== 把传递来的权限组合成dict格式 ================
        form_permission_dict = {}
        # 遍历
        for item in permissions:
            if len(str(item)) >= 3:
                # 获取当前权限的Permission和button
                temp_permission = int(item[:len(item)-2])
                temp_button = int(item[len(item)-2:])
                # 判断是否存在
                if temp_permission not in form_permission_dict:
                    form_permission_dict[temp_permission] = [temp_button]
                else:
                    form_permission_dict[temp_permission].append(temp_button)

        print(form_permission_dict)
        # ==========   从数据库中获取权限  =============
        db_permissions = RolesPermission.objects.filter(roles__id=pk)
        # 定义数据库中权限
        db_permissions_dict = {}
        # 遍历 db_permissions
        for item in db_permissions:
            db_permissions_dict[item.permission_id] = []
            # 查找当前的button权限
            permissiondetail_objs = RolesPermissonDetail.objects.filter(rolespermission_id = item.id)
            # 遍历
            for detail in permissiondetail_objs:
                db_permissions_dict[item.permission_id].append(detail.button_id)

        # ================ 执行权限的添加和删除 ==================
        form_p_keys = list(form_permission_dict.keys())
        db_p_keys = list(db_permissions_dict.keys())

        # ==== 删除的菜单权限 ====
        remove_permission = list(set(db_p_keys) - set(form_p_keys))
        for item in remove_permission:
            # 删除按钮权限
            RolesPermissonDetail.objects.filter(button_id__in=db_permissions_dict.get(item)).delete()
            # 删除菜单权限
            RolesPermission.objects.filter(permission_id = item)

        # ==== 添加的菜单权限 ====
        add_permission = list(set(form_p_keys) - set(db_p_keys))
        for item in add_permission:
            # 添加菜单权限
            RolesPermission.objects.create(roles_id=pk, permission_id=item)
            # 获取刚创建的菜单权限对象
            RolesPermission_obj = RolesPermission.objects.filter(roles_id=pk, permission_id=item).first()
            # 遍历添加按钮权限
            for value in form_permission_dict.get(item):
                RolesPermissonDetail.objects.create(rolespermission_id=RolesPermission_obj.id, button_id=value)


        # ================= 修改具体权限 ====================================
        for item in form_permission_dict.keys():
            # ==获取要删除的权限 ==
            del_button_list = list(set(db_permissions_dict.get(item)) - set(form_permission_dict.get(item)))
            # 删除
            RolesPermissonDetail.objects.filter(button_id__in=del_button_list).delete()

            # == 获取要添加的按钮权限 ===
            add_button_list = list(set(form_permission_dict.get(item)) - set(db_permissions_dict.get(item)))
            # 获取具体权限对象
            RolesPermission_obj = RolesPermission.objects.filter(roles_id=pk, permission_id=item).first()
            # 遍历添加按钮权限
            for value in add_button_list:
                RolesPermissonDetail.objects.create(rolespermission_id=RolesPermission_obj.id, button_id=value)


        return Response(status=status.HTTP_200_OK)
        """


# ===== 用户登录的认证 ===========
class LoginView(APIView):

    authentication_classes = []

    def post(self, request, *args, **kwargs):
        # 获取传递的用户名和密码
        rec = request.data
        # 1. 当前用户是否存在
        staff_obj = Staff.objects.filter(Q(id=rec.get("id")) | Q(mobile=rec.get('id')) | Q(email=rec.get('id'))).first()
        # === 判断 ===
        if not staff_obj:
            return Response({'error': "当前用户不存在！"}, status=status.HTTP_401_UNAUTHORIZED)
        # 2. 判断当前是否禁用
        if not staff_obj.status:
            return Response({'error': "当前用户已禁用！"}, status=status.HTTP_401_UNAUTHORIZED)
        # 3. 判断密码是否正确
        if staff_obj.pwd != rec.get('pwd'):
            return Response({'error': "密码错误！"}, status=status.HTTP_401_UNAUTHORIZED)

        # 4. 获取jwt token
        token = jwt_token.create_token({'id': staff_obj.id, 'name': staff_obj.name})

        # 5. 写入上次登录时间
        Staff.objects.filter(id=staff_obj.id).update(last_login=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        # 6. 获取当前用户的角色，分部，业务区信息
        roles_obj = Roles.objects.filter(staff__id=staff_obj.id).first()
        area_obj = BranchArea.objects.filter(areaplace__staff__id=staff_obj.id).first()
        branch_obj = Branch.objects.filter(brancharea=area_obj).first()
        # 定义返回的集合
        res_info = {'id': staff_obj.id, 'name': staff_obj.name}
        # 判断是不是管理员
        if roles_obj.name == "普通员工":
            res_info['branch'] = branch_obj.id
            res_info['area'] = area_obj.id
            res_info['roles'] = "普通员工"
        elif roles_obj.name in ['业务区管理员', '业务区工单管理员']:
            res_info['branch'] = branch_obj.id
            res_info['area'] = area_obj.id
            res_info['roles'] = ""
        elif roles_obj.name in ['大区管理员', '大区工单管理员']:
            res_info['branch'] = branch_obj.id
            res_info['area'] = ""
            res_info['roles'] = ""
        else:
            res_info['branch'] = ""
            res_info['area'] = ""
            res_info['roles'] = ""



        # 返回
        return Response({'token': token, 'staff': res_info}, status=status.HTTP_200_OK)


# ===== 验证码的views ==============
class ImageCodeView(APIView):

    authentication_classes = []

    def get(self, request, *args, **kwargs):
        # 获取验证码和图片
        image_obj, code = check_code()
        # 实例化一个ByteIO的对象
        stream = BytesIO()
        # 把图片保存在内存中, 并没有存储在硬盘中！
        image_obj.save(stream, 'png')
        # 返回
        return HttpResponse(stream.getvalue())


# ======= 权限条目的views ===========
class PermissionViews(ModelViewSet):
    queryset = AreaPlace.objects.all()
    serializer_class = PermissionSerializer

    # authentication_classes = []
    @action(methods=['get'], detail=False)
    def select(self, request, *args, **kwargs):

        # 获取所有的权限条目
        objs_permission = Permission.objects.all()
        # 定义一个集合
        results = []
        # 遍历
        for item in objs_permission:
            # 定义一个字典
            temp_dict = {}
            # 实例化
            if item.parent == 0:
                # 附加
                results.append({'id':item.id, 'label':item.title,'url':item.url,'icon':item.icon,
                                'order':item.order, 'parent':item.parent,'children':[] })
                # 跳出
                continue

            # 遍历rensult
            for index, value in enumerate(results):
                if value.get('id') == item.parent:  # 二级菜单该挂到哪个顶级菜单下
                    # 定义一个List集合
                    permission_sub_buttons = []
                    # 获取当前页面的挂在的按钮
                    button_objs = Button.objects.filter(permission__id=item.id)
                    # 获取当前页面所有按钮的名称
                    button_names = list(button_objs.values_list('name', flat=True))
                    # 遍历
                    for sub_value in button_objs:
                        permission_sub_buttons.append({'id': "%d%02d" % (item.id, sub_value.id), 'label':sub_value.name})
                    #把当前页面的按钮添加到树形结构的第三层
                    results[index]['children'].append({'id':item.id, 'label':item.title,'url':item.url,'icon':item.icon,
                                'order':item.order, 'parent':item.parent, 'buttons': button_names,'children': permission_sub_buttons})


        return Response({'data': results})

    @action(methods=['get'], detail=False)
    def display(self, request, *args, **kwargs):

        # 获取所有的权限条目
        objs_permission = Permission.objects.all()
        # 定义一个集合
        results = []
        # 遍历
        for item in objs_permission:
            # 定义一个字典
            temp_dict = {}
            # 实例化
            if item.parent == 0:
                # 附加
                results.append({'id': item.id, 'label': item.title, 'url': item.url, 'icon': item.icon,
                                'order': item.order, 'parent': item.parent, 'children': []})
                # 跳出
                continue

            # 遍历rensult
            for index, value in enumerate(results):
                if value.get('id') == item.parent:  # 二级菜单该挂到哪个顶级菜单下
                    # 定义一个List集合
                    permission_sub_buttons = []
                    # 获取当前页面的挂在的按钮
                    button_objs = Button.objects.filter(permission__id=item.id)
                    # 获取当前页面所有按钮的名称
                    button_names = list(button_objs.values_list('name', flat=True))
                    # 遍历
                    for sub_value in button_objs:
                        permission_sub_buttons.append(
                            {'id': "%d%02d" % (item.id, sub_value.id), 'label': sub_value.name})
                    # 把当前页面的按钮添加到树形结构的第三层
                    results[index]['children'].append(
                        {'id': item.id, 'label': item.title, 'url': item.url, 'icon': item.icon,
                         'order': item.order, 'parent': item.parent, 'buttons': button_names})


        return Response({'data': results})

    @action(methods=['get'], detail=False)
    def parent(self,request, *args, **kwargs):
        # 获取权限条目中，有父节点的权限条目，并返回父节点的编号
        objs_parent = list(Permission.objects.filter(parent=0).distinct().values('id','title'))

        # 插入一个节点
        objs_parent.insert(0, {'id':0, 'title': '顶级菜单'})
        return Response({'data': objs_parent})

    @action(methods=['get'], detail=False)
    def menu(self, request, *args, **kwargs):

        # 获取当前登录的用户
        current_user = request.user.get("id")
        # 获取当前用户登录的权限
        obj_current_permissions = Permission.objects.filter(rolespermission__roles__staff__id=current_user).distinct()
        # 添加父页面
        obj_current_permissions_id = list(Permission.objects.filter(rolespermission__roles__staff__id=current_user).distinct().values_list('id', flat=True))
        # 定义一个集合存储构建号的权限菜单
        objs_permission_ex = []  # {1: 100, 2:111, 3:110}
        # 遍历当前权限
        for item in obj_current_permissions:
            # 判断是否是父节点
            if item.parent != 0 and item.parent not in obj_current_permissions_id:
                # 把父节点加入objs_permission_ex
                # 获取当前的父对象：
                obj_parent = (Permission.objects.get(id=item.parent))
                # 判断是否存在objs_permission_ex集合中
                if obj_parent.id not in objs_permission_ex:
                    objs_permission_ex.append({"id": obj_parent.id, 'order': obj_parent.order})
                # 添加父节点到obj_current_permissions_id
                obj_current_permissions_id.append(obj_parent.id)
            # 添加
            objs_permission_ex.append({"id": item.id, 'order': item.order})


        # 把首页添加进去
        objs_permission_ex.append({'id':1,  'order':1 })
        # 按照order排序【升序】
        objs_permission_ex.sort(key=lambda k: (k.get('order')), reverse=False)

        # 获取所有的key
        objs_permission_ex_sort = []
        # 遍历 id
        for item in objs_permission_ex:
            objs_permission_ex_sort.append(item.get('id'))
        # 获取权限条目--并按照顺序获取！
        objs_permissions = []
        for item in objs_permission_ex_sort:
            objs_permissions.append(Permission.objects.get(id=item))

        results = []

        # objs_permissions = Permission.objects.all()
        # 遍历
        for item in objs_permissions:
            # 定义一个字典
            temp_dict = {}
            # 实例化
        # 定义一个集合
            if item.parent == 0:
                # 附加
                results.append({'id': item.id, 'path': item.url, 'meta':{'title': item.title, 'icon': item.icon}, 'children': []})
                # 跳出
                continue

            # 遍历rensult
            for index, value in enumerate(results):
                if value.get('id') == item.parent:  # 二级菜单该挂到哪个顶级菜单下
                    results[index]['children'].append(
                        {'path': item.url, 'meta':{'title': item.title, 'icon': item.icon}})


        print(results)
        return Response({'data': results})


# ======= 角色权限的明细 ===========
class RolesPerDetail(ModelViewSet):
    queryset = RolesPermissonDetail.objects.all()
    serializer_class = RolesPermissionDetailSerializer

    # authentication_classes = []
    @action(methods=['get','post'], detail=False, url_path="detail/get")
    def get_detail(self, request, *args, **kwargs):
        """获取当前页面的权限明细"""
        # 获取当前登录的用户
        current_user = request.user.get('id')
        roles_obj = Roles.objects.filter(staff__id=current_user).first()
        # 获取当前url
        current_url = request.data.get('url')
        # 获取页面的对象
        page_obj = Permission.objects.filter(url=current_url).first()
        # 获取当前用户所属于的角色在当前页面所具备的按钮权限
        buttons = list(Button.objects.filter(rolespermissondetail__rolespermission__roles=roles_obj,
                                        rolespermissondetail__rolespermission__permission=page_obj
                                        ).values('id', 'name'))
        # 返回
        return Response({'data': buttons}, status=status.HTTP_200_OK)


